#include "/project/public/_public.h"

/*
   本程序用于生成全国气象站点观测的分钟数据
   程序需要3个参数
	1.全国气象站点存放文件inifile
	2.生成的测试数据存放目录outpath
	3.程序运行的日志文件logfile
	
*/
//增加生成历史数据文件的功能,为压缩文件和清理文件模块准备历史数据文件
//增加信号处理函数,处理2和15的信号
//解决调用exit函数退出时局部对象没有调用析构函数的问题.
//把心跳信息写入共享内存

//单条气象数据结构
struct st_stcode
{
	char provname[31];		//省名称
	char obtid[11];			//站号
	char obtname[31];		//站名
	double lat;				//纬度
	double lon;				//经度
	double height;			//海拔高度
};

struct st_surfdata
{
	char obtid[11];			//站点代码
	char ddatetime[21];		//数据时间:格式yyyymmddhh24miss
	int t;					//气温:单位,0,1摄氏度
	int p;					//气压:0.1帕
	int u;					//相对湿度,0-100之间的值
	int wd;					//风向,0-360之间的值
	int wf;					//风速:单位0.1m/s
	int r;					//降雨量:0.1mm
	int vis;				//能见度:0.1m
};



vector<struct st_stcode> vstcode;
vector<st_surfdata> vsurfdata;
//模拟生成全国气象站点分钟观测数据,存放再vsurfdata容器中
void CrtSurfData();

//输出全国气象站点分钟观测数据到文件中datafmt是数据格式outpath是输出的文件位置
bool crtSurfFile(const char* outpath,const char* datafmt);
//日志类
CLogFile logfile;
bool LoadSTCode(const char*);
char strddatetime[21];
//进程的心跳类
CPActive act;
//拼接生成数据的文件名,例如:/tmp/surfdata/SURF_ZH_20210629092200_2254.csv
CFile file;
void errorArg()
{
	printf("Using: ./ inifile outpath logfile datafmt [datetime]\n");
	printf("Example:/project/idc1/bin/crtsurfdata /project/idc1/ini/stcode.ini /tmp/idc/surfdata /log/idc/crtsurfdata.log xml,json,csv 20201007123000\n\n");
	printf("inifile 全国气象站点参数文件名 \n");
	printf("outpath 全国气象站点数据文件存放的目录.\n");
	printf("logfile 本程序运行的日志文件名.\n\n");
	printf("datetime 这是一个可选参数,表示生成指定时间的数据和文件 \n\n");
	return;
}

void EXIT(int sig);	//信号处理函数

int main(int argc,char* argv[])
{
	//printf("argc = %d\n",argc);
	if((argc != 5)&&(argc != 6))
	{
		printf("error argc != 5 && argc != 6");
		errorArg();
		return -1;
	}
	else if(strstr(argv[4],"xml")==NULL && strstr(argv[4],"csv")==NULL && strstr(argv[4],"json")==NULL)
	{
		printf("文件格式错误");
		errorArg();
		return -1;
	}
	
	//关闭所有的先后和输入输出
	//设置信号,在shell状态下可用"kill+进程号"正常终止这些进程
	//但请不要用"kill -9 +进程号"强行终止
	CloseIOAndSignal(true);
	signal(SIGINT,EXIT);
	signal(SIGTERM,EXIT);

	if(logfile.Open(argv[3]) == false)
	{
		printf("logfile.Open(%s) failed.\n",argv[3]);
		return -1;
	}

	logfile.Write("crtsurfdata 开始运行.\n");

	act.AddPInfo(60,argv[0],&logfile);

	//这里插入业务代码
	if(LoadSTCode(argv[1]) == false) return -1;
	
	logfile.Write("LoadSTCode success\n");
	//获取当前时间
	memset(strddatetime,0,sizeof strddatetime);
	if(5 == argc)
	{
		LocalTime(strddatetime,"yyyymmddhh24miss");
	}
	else
	{
		STRCPY(strddatetime,sizeof strddatetime,argv[5]);
	}

	CrtSurfData();
	if(strstr(argv[4],"xml") != NULL)
	{
		crtSurfFile(argv[2],"xml");
	}
	
	if(strstr(argv[4],"json") != NULL)
	{
		crtSurfFile(argv[2],"json");
	}
	
	
	if(strstr(argv[4],"csv") != NULL)
	{
		crtSurfFile(argv[2],"csv");
	}

	logfile.Write("crtsurfdata 运行结束.\n");
	return 0;
}

//读取站点参数文件中的内容加载到vscode容器中
bool LoadSTCode(const char* inifile)
{
	CFile file;

	//打开站点参数文件
	if(file.Open(inifile,"r") == false)
	{
		logfile.Write("file.Open(%s) failed.\n",inifile);
		return false;
	}

	char strBuffer[301];
	CCmdStr cmdstr;
	struct st_stcode stcode;
	while(true)
	{
		if(file.Fgets(strBuffer,300,true) == false) break;

		//把读取到的一行拆分
		cmdstr.SplitToCmd(strBuffer,",",true);
		if(cmdstr.CmdCount() != 6) 
			continue;
		//把站点参数的每一个数据线保存到站点参数结构体中
		cmdstr.GetValue(0, stcode.provname,30);
		cmdstr.GetValue(1, stcode.obtid,30);
		cmdstr.GetValue(2, stcode.obtname,30);
		cmdstr.GetValue(3,&stcode.lat);
		cmdstr.GetValue(4,&stcode.lon);
		cmdstr.GetValue(5,&stcode.height);
		vstcode.emplace_back(std::move(stcode));
	}
	return true;
}

void CrtSurfData()
{
	srand(time(NULL));

	st_surfdata stsurfdata;
	//遍历气象站点参数的vscode容器
	for(unsigned long ii = 0; ii<vstcode.size();++ii)
	{
		memset(&stsurfdata,0,sizeof stsurfdata);
		//用随机术填充分钟观测数据的结构体
		strncpy(stsurfdata.obtid, vstcode[ii].obtid,10);		//站点代码
		strncpy(stsurfdata.ddatetime, strddatetime,14);			//数据时间:格式为yyyymmddhh24miss
		stsurfdata.t = rand()%351;								//气温:0.1摄氏度
		stsurfdata.p = rand()%265+10000;						//气压:0.1百帕
		stsurfdata.u = rand()%100+1;							//相对湿度,0-100
		stsurfdata.wd = rand()%360;								//风向0-360
		stsurfdata.wf= rand()%150;							//风速:0.1m/s
		stsurfdata.r = rand()%16;								//降雨量:0.1mm
		stsurfdata.vis = rand()%5001+100000;					//能见度:0.1米

		//把观测数据的结构体放入vsurfdata容器
		vsurfdata.emplace_back(stsurfdata);

	}
	printf("aaa\n");
	printf("bbb\n");
	return;

}

bool crtSurfFile(const char* outpath,const char* datafmt)
{
	char strFileName[301];
	sprintf(strFileName,"%s/SURF_ZH_%s_%d.%s",outpath,strddatetime,static_cast<int>(getpid()),datafmt);

	//打开文件
	if(file.OpenForRename(strFileName,"w") == false)
	{
		logfile.Write("file.OpenForRename(%s) failed.\n",strFileName);
		return false;
	}

	if( 0 == strcmp(datafmt,"xml"))
	{
		//写入第一行标题
		file.Fprintf("<data>\n");
		for(unsigned long i = 0; i < vsurfdata.size(); ++i)
		{
			file.Fprintf("<obtid>%s</obtid><ddatetime>%s</ddatetime><t>%lf</t><p>%lf</p><u>%d</u><wd>%d</wd><wf>%lf</wf><r>%lf</r><vis>%lf</vis><endl/>\n",vsurfdata[i].obtid,vsurfdata[i].ddatetime
			,vsurfdata[i].t/10.0,vsurfdata[i].p/10.0,vsurfdata[i].u,vsurfdata[i].wd,vsurfdata[i].wf/10.0
			,vsurfdata[i].r/10.0,vsurfdata[i].vis/10.0);
		}
		file.Fprintf("</data>");

	}
	else if(0 == strcmp(datafmt,"json"))
	{
		//写入第一行标题
		file.Fprintf("{\n\"data\":[\n");
		for(unsigned long i = 0; i < vsurfdata.size(); ++i)
		{
			file.Fprintf("{\"obtid\":\"%s\",\"ddatetime\":\"%s\",\"t\":\"%lf\",\"p\":\"%lf\",\"u\":\"%d\",\"wd\":\"%d\",\"wf\":\"%lf\",\"r\":\"%lf\",\"vis\":\"%lf\"}\n",vsurfdata[i].obtid,vsurfdata[i].ddatetime,vsurfdata[i].t/10.0,vsurfdata[i].p/10.0,vsurfdata[i].u,vsurfdata[i].wd,vsurfdata[i].wf/10.0,vsurfdata[i].r/10.0,vsurfdata[i].vis/10.0);
		}
		file.Fprintf("]\n}");

	}
	else if(0 == strcmp(datafmt,"csv"))
	{
		//写入第一行标题
		file.Fprintf("站点代码,数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度\n");

	//遍历存放观测数据的vsurfdata容器
		for(unsigned long i = 0; i < vsurfdata.size(); ++i)
		{
			file.Fprintf("%s,%s,%lf,%lf,%d,%d,%lf,%lf,%lf\n",vsurfdata[i].obtid,vsurfdata[i].ddatetime
			,vsurfdata[i].t/10.0,vsurfdata[i].p/10.0,vsurfdata[i].u,vsurfdata[i].wd,vsurfdata[i].wf/10.0
			,vsurfdata[i].r/10.0,vsurfdata[i].vis/10.0);
		}
	}
	//关闭文件
	file.CloseAndRename();
	UTime(strFileName,strddatetime);//修改文件时间
	logfile.Write("生成数据文件%s成功,数据时间%s,记录数%d.\n",strFileName,strddatetime,vsurfdata.size());
	return true;
}

void EXIT(int sig)
{
	logfile.Write("程序退出,sig = %d\n\n",sig);

	exit(0);
}
